package com.xjoyt.pay.share.services;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.xjoyt.pay.abstracts.AbstractService;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.dto.PageParam;
import com.xjoyt.pay.dto.PageResult;
import com.xjoyt.pay.share.api.sms.SmsBaoClient;
import com.xjoyt.pay.share.dto.PhoneCodeResult;
import com.xjoyt.pay.share.params.PhoneCodeParam;
import com.xjoyt.pay.share.params.SmsPageParam;
import com.xjoyt.pay.share.po.Sms;
import com.xjoyt.pay.share.repository.SmsRepository;

@Service
public class SmsService extends AbstractService {

	private static final String SMS_CODE_KEY = "key:value.phone.code.%s.%s.%s";

	private static final int CODE_LENGTH = 6;

	private static final int CODE_TIMEOUT = 30;

	private static final int COOLDOWN_TIME = 1;

	@Value("${spring.profiles.active}")
	private String active;

	@Autowired
	private SmsBaoClient smsBaoClient;

	@Autowired
	private SmsRepository repository;

	@Autowired
	private StringRedisTemplate redisTemplate;

	public ExecuteResult<String> sendCode(PhoneCodeParam param) {
		Sms entity = new Sms();
		entity.companyId = param.companyId;
		entity.companyName = param.companyName;
		entity.phone = param.phone;
		entity.addedDate = new Date();
		ExecuteResult<String> executeResult = null;

		String key = String.format(SMS_CODE_KEY, param.action, param.companyId, param.phone);
		if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(key + ".time"))) {
			return ExecuteResult.fail("验证码已经发送");
		}
		String code = redisTemplate.opsForValue().get(key);
		if (StringUtils.isBlank(code)) {
			code = getPhoneCode();
		}
		if ("dev".equals(active)) {
			entity.content = "开发模式验证码发送：" + code;
			entity.success = true;
			System.out.println(entity.content);
			redisTemplate.opsForValue().set(key, code, CODE_TIMEOUT, TimeUnit.MINUTES);
			redisTemplate.opsForValue().set(key + ".time", code, COOLDOWN_TIME, TimeUnit.MINUTES);
			executeResult = ExecuteResult.ok(code);
		} else {
			try {
				ExecuteResult<PhoneCodeResult> result = smsBaoClient.sendCode(param, code);
				if (result.isSuccess()) {
					entity.content = result.getValue().content;
					entity.success = true;
					executeResult = ExecuteResult.ok(result.getValue().value);
				} else {
					entity.success = false;
					entity.content = "验证码:" + code + "，发送失败";
					executeResult = ExecuteResult.fail(result.getMessage());
				}
				redisTemplate.opsForValue().set(key, code, CODE_TIMEOUT, TimeUnit.MINUTES);
				redisTemplate.opsForValue().set(key + ".time", code, COOLDOWN_TIME, TimeUnit.MINUTES);
			} catch (Exception e) {
				e.printStackTrace();
				entity.success = false;
				entity.content = "验证码:" + code + "，发送异常";
				executeResult = ExecuteResult.fail("发送失败");
			}
		}
		repository.save(entity);
		return executeResult;
	}

	public ExecuteResult<String> validate(PhoneCodeParam param) {
		String key = String.format(SMS_CODE_KEY, param.action, param.companyId, param.phone);
		String value = redisTemplate.opsForValue().get(key);
		if (!param.code.equals(value)) {
			return ExecuteResult.fail("验证码有误");
		}
		return ExecuteResult.ok();
	}

	public ExecuteResult<?> remove(PhoneCodeParam param) {
		String key = String.format(SMS_CODE_KEY, param.action, param.companyId, param.phone);
		String value = redisTemplate.opsForValue().get(key);
		if (StringUtils.isNotBlank(value)) {
			redisTemplate.delete(key);
		}
		return ExecuteResult.ok();
	}

	public PageResult<Sms> loadPage(PageParam<SmsPageParam> param) {
		return repository.loadPage(param);
	}

	private String getPhoneCode() {
		StringBuilder builder = new StringBuilder();
		int codeLength = CODE_LENGTH;
		for (int i = 0; i < codeLength; i++) {
			java.util.Random random = new java.util.Random();
			int r = random.nextInt(10);
			builder.append(String.valueOf(r));
		}
		return builder.toString();
	}

}
